home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 109 / EnigmaAmiga109CD.iso / dalla rivista / amiga.free / diropus4.12b_gpl / config / main.c < prev    next >
C/C++ Source or Header  |  2000-01-27  |  40KB  |  1,559 lines

  1. /*
  2.  
  3. Directory Opus 4
  4. Original GPL release version 4.12
  5. Copyright 1993-2000 Jonathan Potter
  6.  
  7. This program is free software; you can redistribute it and/or
  8. modify it under the terms of the GNU General Public License
  9. as published by the Free Software Foundation; either version 2
  10. of the License, or (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. All users of Directory Opus 4 (including versions distributed
  22. under the GPL) are entitled to upgrade to the latest version of
  23. Directory Opus version 5 at a reduced price. Please see
  24. http://www.gpsoft.com.au for more information.
  25.  
  26. The release of Directory Opus 4 under the GPL in NO WAY affects
  27. the existing commercial status of Directory Opus 5.
  28.  
  29. */
  30.  
  31. #include "config.h"
  32.  
  33. #define LIB_VER 22
  34.  
  35. int CXBRK(void);
  36. void chkabort(void);
  37.  
  38. int  CXBRK(void) { return(0); }  /* Disable Lattice CTRL/C handling */
  39. void chkabort(void) { return; } 
  40.  
  41. main(argc,argv)
  42. int argc;
  43. char *argv[];
  44. {
  45.     ULONG class;
  46.     USHORT gadgetid,code;
  47.     int num,a;
  48.     char portname[50],rportname[50],oldconfigname[256],oldlanguage[30];
  49.     struct WBStartup *wbmsg;
  50.     struct ConfigUndo *undo;
  51.  
  52. #ifdef DEBUG
  53.     if (sizeof(struct Config)!=CONFIG_STRUCTURE_SIZE) {
  54.         printf("invalid config size - %ld - should be %ld\n",sizeof(struct Config),CONFIG_STRUCTURE_SIZE);
  55.         _exit(0);
  56.     }
  57. #endif
  58.  
  59.     if (!(DOpusBase=(struct DOpusBase *)OpenLibrary("dopus.library",LIB_VER)) &&
  60.         !(DOpusBase=(struct DOpusBase *)OpenLibrary("dopus:libs/dopus.library",LIB_VER)))
  61.         _exit(0);
  62.  
  63.     GfxBase=DOpusBase->GfxBase;
  64.     LayersBase=(struct Library *)DOpusBase->LayersBase;
  65.     IntuitionBase=DOpusBase->IntuitionBase;
  66.  
  67.     WorkbenchBase=IconBase=NULL;
  68.  
  69.     DiskfontBase=OpenLibrary("diskfont.library",0);
  70.     WorkbenchBase=OpenLibrary("workbench.library",37);
  71.     IconBase=OpenLibrary("icon.library",0);
  72.     PPBase=OpenLibrary("powerpacker.library",0);
  73.  
  74.     network=0;
  75.  
  76.     Forbid();
  77.     if (FindName(&SysBase->LibList,"services.library")) {
  78.         network=1;
  79.         formatgads[7].NextGadget=&formatgads[8];
  80.     }
  81.     Permit();
  82.  
  83.     if (SysBase->LibNode.lib_Version>=40) version2=OSVER_40;
  84.     else if (SysBase->LibNode.lib_Version==39) version2=OSVER_39;
  85.     else if (SysBase->LibNode.lib_Version==38) version2=OSVER_38;
  86.     else if (SysBase->LibNode.lib_Version==37) version2=OSVER_37;
  87.     else version2=OSVER_34;
  88.  
  89.     if (version2<OSVER_37) {
  90.         operationgadgets[OP_UPDATE][10].type=CTYPE_SKIP;
  91.         systemgadgets[SYS_CLOCK][18].type=CTYPE_SKIP;
  92.         scr_generalgadgets[7].type=CTYPE_SKIP;
  93.     }
  94.     if (version2<OSVER_39) {
  95.         scr_generalgadgets[6].type=CTYPE_SKIP;
  96.         systemgadgets[SYS_VIEWPLAY][4].type=CTYPE_SKIP;
  97.         systemgadgets[SYS_VIEWPLAY][5].type=CTYPE_SKIP;
  98.     }
  99.     else if (!(GfxBase->ChipRevBits0&GFXF_AA_ALICE)) {
  100.         systemgadgets[SYS_VIEWPLAY][4].type=CTYPE_SKIP;
  101.     }
  102.  
  103.     /* ExAll() */
  104.  
  105.     if (version2<OSVER_40) {
  106.         systemgadgets[SYS_DIRECTORIES][11].type=CTYPE_SKIP;
  107.     }
  108.  
  109.     conport=cmdport=appport=NULL; appobject=NULL;
  110.     mainkey=buttonkey=gadgetkey=tickkey=clipkey=fontkey=NULL;
  111.     firsttype=NULL; firstbank=curbank=NULL; typekey=NULL; firsthotkey=NULL;
  112.     Screen=NULL; Window=NULL; myproc=NULL; tfont=NULL;
  113.     tickgad=maingad=gadgads=drivegads=menugads=NULL; firstclip=NULL;
  114.     undoconfig=NULL; config=NULL; changed=lchanged=clipcount=tickcount=0;
  115.     curoperation=-1; fontdatabuf=NULL; helpbuffer=NULL; helpkey=NULL;
  116.     cfg_string=NULL;
  117.     stringdata.string_table=NULL;
  118.     stringdata.string_buffer=NULL;
  119.  
  120.     free_colour_table(NULL);
  121.  
  122.     help_ok=1;
  123.  
  124. /*
  125.     clip_port=NULL; clip_io=NULL;
  126. */
  127.     currenthelpname[0]=0;
  128.  
  129.     if (!(FindSystemFile("DirectoryOpus.CFG",configname,256,SYSFILE_DATA))) {
  130.         if (CheckExist("DOpus:S",NULL)) strcpy(configname,"DOpus:S/DirectoryOpus.CFG");
  131.         else strcpy(configname,"s:DirectoryOpus.CFG");
  132.     }
  133.  
  134.     FindSystemFile("DirectoryOpus.CLA",classname,256,SYSFILE_DATA);
  135.  
  136.     if (!argc) {
  137.         wbmsg=(struct WBStartup *)argv;
  138.         if (wbmsg->sm_NumArgs>1) {
  139.             num=atoi(wbmsg->sm_ArgList[1].wa_Name);
  140.             lsprintf(portname,"dopus4_config_port%ld",num);
  141.             if (!(conport=LCreatePort(portname,20))) quit();
  142.             lsprintf(rportname,"dopus4_config_reply%ld",num);
  143.             Forbid();
  144.             if (!(cmdport=FindPort(rportname))) {
  145.                 LDeletePort(conport);
  146.                 conport=NULL;
  147.             }
  148.             Permit();
  149.         }
  150.     }
  151.  
  152.     myproc=(struct Process *)FindTask(0);
  153.     wsave=myproc->pr_WindowPtr;
  154.     myproc->pr_WindowPtr=(APTR)-1;
  155.  
  156.     for (a=0;a<12;a++)
  157.         if (!(functypelist[a]=LAllocRemember(&mainkey,40,MEMF_CLEAR))) quit();
  158.     functypelist[12]=NULL;
  159.  
  160.     if (!cmdport && !(config=(struct Config *)AllocMem(sizeof(struct Config),MEMF_CLEAR)))
  161.         quit();
  162.     getconfig();
  163.     strcpy(oldconfigname,configname);
  164.  
  165.     appport=LCreatePort(NULL,0);
  166. /*
  167.     if (clip_port=LCreatePort(NULL,0))
  168.         clip_io=(struct IOClipReq *)LCreateExtIO(clip_port,sizeof(struct IOClipReq));
  169. */
  170.  
  171.     read_strings();
  172.     load_clips();
  173.     readhelp();
  174.  
  175.     if (config->scrdepth<2) config->scrdepth+=2;
  176.  
  177.     open_screen();
  178.  
  179.     undo=makeundo(UNDO_ALL);
  180.     showconfigscreen(CFG_MAINMENU);
  181.     giveconfig();
  182.  
  183.     FOREVER {
  184.         Wait(1<<Window->UserPort->mp_SigBit);
  185.         while (IMsg=getintuimsg()) {
  186.             class=IMsg->Class; code=IMsg->Code;
  187.             if (class==GADGETUP || class==GADGETDOWN)
  188.                 gadgetid=((struct Gadget *)IMsg->IAddress)->GadgetID;
  189.             ReplyMsg((struct Message *)IMsg);
  190.             switch (class) {
  191.                 case MENUPICK:
  192.                     if (code==MENUNULL) break;
  193.                     switch ((num=ITEMNUM(code))) {
  194.                         case 0:
  195.                         case 1:
  196.                             if (lchanged && !request(cfg_string[STR_REALLY_DISCARD_CONFIG]))
  197.                                 break;
  198.                             strcpy(oldlanguage,config->language);
  199.                             if (doload(CFG_MAINMENU,num)) {
  200.                                 if (strcmp(config->language,oldlanguage)) {
  201.                                     busy();
  202.                                     read_strings();
  203.                                     readhelp();
  204.                                     unbusy();
  205.                                 }
  206.                                 close_screen();
  207.                                 open_screen();
  208.                                 configmsg(CONFIG_NEW_HOTKEY);
  209.                                 showconfigscreen(CFG_MAINMENU);
  210.                             }
  211.                             break;
  212.                     }
  213.                     break;
  214.                 case GADGETUP:
  215.                     curoperation=gadgetid;
  216.                     switch (gadgetid) {
  217.                         case CFG_DRIVE:
  218.                             if (dodriveconfig()) lchanged=1;
  219.                             showconfigscreen(CFG_MAINMENU);
  220.                             break;
  221.                         case CFG_FILETYPE:
  222.                             if (dofiletypeconfig()) lchanged=1;
  223.                             showconfigscreen(CFG_MAINMENU);
  224.                             break;
  225.                         case CFG_GADGET:
  226.                             if (dogadgetconfig()) lchanged=1;
  227.                             showconfigscreen(CFG_MAINMENU);
  228.                             break;
  229.                         case CFG_HOTKEYS:
  230.                             if (dohotkeysconfig()) lchanged=1;
  231.                             showconfigscreen(CFG_MAINMENU);
  232.                             break;
  233.                         case CFG_MENU:
  234.                             if (domenuconfig()) lchanged=1;
  235.                             showconfigscreen(CFG_MAINMENU);
  236.                             break;
  237.                         case CFG_OPERATION:
  238.                             if (dooperationconfig()) lchanged=1;
  239.                             showconfigscreen(CFG_MAINMENU);
  240.                             break;
  241.                         case CFG_SCREEN:
  242.                             if (doscreenconfig()) lchanged=1;
  243.                             showconfigscreen(CFG_MAINMENU);
  244.                             break;
  245.                         case CFG_SYSTEM:
  246.                             if (dosystemconfig()) lchanged=1;
  247.                             showconfigscreen(CFG_MAINMENU);
  248.                             break;
  249.                         case CFG_SAVE:
  250.                             dosave(0);
  251.                             break;
  252.                         case CFG_OKAY:
  253.                         case CFG_CANCEL:
  254.                             if ((gadgetid==CFG_CANCEL || !cmdport) && lchanged &&
  255.                                 !do_request(cfg_string[STR_EXIT_WITHOUT_SAVING],
  256.                                     cfg_string[STR_OKAY_TO_QUIT],cfg_string[STR_CANCEL]))
  257.                                 break;
  258.                             if (gadgetid==CFG_CANCEL) {
  259.                                 doundo(undo,UNDO_ALL);
  260.                                 strcpy(configname,oldconfigname);
  261.                             }
  262.                             doundo(undo,0);
  263.                             quit();
  264.                 }
  265.                 curoperation=-1;
  266.             }
  267.         }
  268.     }
  269. }
  270.  
  271. void quit()
  272. {
  273.     if (Window) SetBusyPointer(Window);
  274.     if (cmdport) {
  275.         giveconfig();
  276.         configmsg(CONFIG_ALL_DONE);
  277.     }
  278.     else {
  279.         fixcstuff(&cstuff);
  280.         FreeConfig(&cstuff);
  281.         if (config) FreeMem(config,sizeof(struct Config));
  282.     }
  283.     if (myproc) myproc->pr_WindowPtr=wsave;
  284.     if (firstclip) save_clips();
  285.     if (Screen) ScreenToBack(Screen);
  286.     close_screen();
  287.     FreeStringFile(&stringdata);
  288.     if (conport) LDeletePort(conport);
  289.     if (appport) LDeletePort(appport);
  290.     if (tfont) CloseFont(tfont);
  291. /*
  292.     if (clip_io) LDeleteExtIO((struct IORequest *)clip_io);
  293.     if (clip_port) LDeletePort(clip_port);
  294. */
  295.     LFreeRemember(&mainkey);
  296.     LFreeRemember(&clipkey);
  297.     LFreeRemember(&gadgetkey);
  298.     LFreeRemember(&tickkey);
  299.     LFreeRemember(&fontkey);
  300.     LFreeRemember(&helpkey);
  301.     LFreeRemember(&buttonkey);
  302.     if (DiskfontBase) CloseLibrary(DiskfontBase);
  303.     if (WorkbenchBase) CloseLibrary(WorkbenchBase);
  304.     if (IconBase) CloseLibrary(IconBase);
  305.     if (PPBase) CloseLibrary(PPBase);
  306.     CloseLibrary((struct Library *)DOpusBase);
  307.     _exit(0);
  308. }
  309.  
  310. void getconfig()
  311. {
  312.     struct configconfig *cfg;
  313.  
  314.     if (cmdport) {
  315.         configmsg(CONFIG_GET_CONFIG);
  316.         cfg=(struct configconfig *)msg.buffer;
  317.         config=cfg->config;
  318.         firsttype=cfg->firsttype;
  319.         firstbank=cfg->firstbank;
  320.         firsthotkey=cfg->firsthotkey;
  321.         typekey=cfg->typekey;
  322.         changed=cfg->changed;
  323.         strcpy(configname,cfg->configname);
  324.         StrConcat(configname,".CFG",256);
  325.         strcpy(loadnamebuf,configname);
  326.     }
  327.     else readconfig();
  328. }
  329.  
  330. void giveconfig()
  331. {
  332.     struct configconfig cfg;
  333.     char *ptr;
  334.  
  335.     if (cmdport) {
  336.         cfg.config=config;
  337.         cfg.firsttype=firsttype;
  338.         cfg.firstbank=firstbank;
  339.         cfg.firsthotkey=firsthotkey;
  340.         cfg.typekey=typekey;
  341.         if (lchanged || changed) cfg.changed=1;
  342.         else cfg.changed=0;
  343.         strcpy(cfg.configname,configname);
  344.         if (ptr=strstri(cfg.configname,".CFG")) *ptr=0;
  345.         cfg.Window=Window;
  346.         cfg.Screen=Screen;
  347.         msg.buffer=(char *)&cfg;
  348.         configmsg(CONFIG_HERES_CONFIG);
  349.     }
  350. }
  351.  
  352. void readconfig()
  353. {
  354.     fixcstuff(&cstuff);
  355.     if ((ReadConfig(configname,&cstuff))!=1) DefaultConfig(&cstuff);
  356.     strcpy(loadnamebuf,configname);
  357.     cstufffix(&cstuff);
  358. }
  359.     
  360. void configmsg(command)
  361. int command;
  362. {
  363.     if (cmdport) {
  364.         msg.msg.mn_Node.ln_Type=NT_MESSAGE;
  365.         msg.msg.mn_ReplyPort=conport;
  366.         msg.msg.mn_Length=(UWORD)sizeof(struct dopusconfigmsg);
  367.         msg.command=command;
  368.         PutMsg(cmdport,(struct Message *)&msg);
  369.         WaitPort(conport);
  370.         GetMsg(conport);
  371.     }
  372. }
  373.  
  374. void fixcstuff(cstuff)
  375. struct ConfigStuff *cstuff;
  376. {
  377.     cstuff->config=config;
  378.     cstuff->typekey=typekey;
  379.     cstuff->firsttype=firsttype;
  380.     cstuff->firstbank=firstbank; cstuff->curbank=curbank;
  381.     cstuff->firsthotkey=firsthotkey;
  382.     if (!Screen && Window) {
  383.         config->config_x=Window->LeftEdge;
  384.         config->config_y=Window->TopEdge;
  385.     }
  386. }
  387.  
  388. void cstufffix(cstuff)
  389. struct ConfigStuff *cstuff;
  390. {
  391.     config=cstuff->config;
  392.     typekey=cstuff->typekey;
  393.     firsttype=cstuff->firsttype;
  394.     firstbank=cstuff->firstbank; curbank=cstuff->curbank;
  395.     firsthotkey=cstuff->firsthotkey;
  396. }
  397.  
  398. void cleanconfigscreen()
  399. {
  400.     struct Gadget *gad;
  401.     struct Message *msg;
  402.  
  403.     FOREVER {
  404.         gad=Window->FirstGadget;
  405.         while (gad) {
  406.             if (!(gad->GadgetType>YP_SYSGADGET)) {
  407.                 RemoveGList(Window,gad,1);
  408.                 break;
  409.             }
  410.             gad=gad->NextGadget;
  411.         }
  412.         if (!gad) break;
  413.     }
  414.  
  415.     SetDrMd(rp,JAM2);
  416.     SetAPen(rp,screen_pens[0].pen);
  417.     RectFill(rp,
  418.         x_off,y_off,
  419.         x_bot,y_bot);
  420.  
  421.     SetBPen(rp,screen_pens[1].pen);
  422.     SetBPen(rp,screen_pens[0].pen);
  423.  
  424.     LFreeRemember(&gadgetkey);
  425.     removetickgads();
  426.  
  427.     while (msg=GetMsg(Window->UserPort))
  428.         ReplyMsg(msg);
  429. }
  430.  
  431. void showconfigscreen(scr)
  432. int scr;
  433. {
  434.     cleanconfigscreen();
  435.  
  436.     switch (scr) {
  437.         case CFG_MAINMENU:
  438.             doscreentitle(cfg_string[STR_CONFIGURATION_MAIN_SCREEN]);
  439.             initsidegads(mainmenugads,0,1);
  440.             break;
  441.  
  442.         case CFG_OPERATION:
  443.             initsidegads(operationgads,1,1);
  444.             doscreentitle(cfg_string[STR_OPERATION_SCREEN]);
  445.             break;
  446.  
  447.         case CFG_GADGET:
  448.             if (gadgads) {
  449.                 AddGadgets(Window,
  450.                     gadgads,
  451.                     NULL,
  452.                     84,
  453.                     screen_pens[config->gadgettopcol].pen,screen_pens[config->gadgetbotcol].pen,1);
  454.             }
  455.             initsidegads(gadgetgads,0,0);
  456.             maingad[GAD_COPYGADGET].Activation|=GACT_TOGGLESELECT;
  457.             maingad[GAD_SWAPGADGET].Activation|=GACT_TOGGLESELECT;
  458.             maingad[GAD_DELETEGADGET].Activation|=GACT_TOGGLESELECT;
  459.             SetAPen(rp,screen_pens[1].pen);
  460.             UScoreText(rp,cfg_string[STR_LEFT_MOUSE_BUTTON],x_off+38,y_off+71,-1);
  461.             BltTemplate((char *)uparrow_data,0,2,rp,x_off+179,y_off+66,12,6);
  462.             UScoreText(rp,cfg_string[STR_RIGHT_MOUSE_BUTTON],x_off+454,y_off+75,-1);
  463.             BltTemplate((char *)downarrow_data,0,2,rp,x_off+437,y_off+70,12,6);
  464.  
  465.         case CFG_MENU:
  466.             if (scr==CFG_MENU) {
  467.                 if (menugads) AddGList(Window,menugads,-1,MENUCOUNT+5-(HIDDENLINES*5),NULL);
  468.                 initsidegads(menugadgets,1,0);
  469.                 maingad[MENU_OKAY].Activation&=~GACT_TOGGLESELECT;
  470.                 maingad[MENU_CANCEL].Activation&=~GACT_TOGGLESELECT;
  471.                 AddGList(Window,menuslidergads,-1,3,NULL);
  472.                 AddGadgets(Window,
  473.                     &menuslidergads[1],
  474.                     NULL,
  475.                     2,
  476.                     screen_pens[config->gadgettopcol].pen,screen_pens[config->gadgetbotcol].pen,0);
  477.                 do3dbox(x_off+612,y_off+21,12,144-HIDDENLINES*8);
  478.                 DoArrow(rp,
  479.                     x_off+612,y_off+119,
  480.                     12,6,
  481.                     screen_pens[config->arrowfg].pen,screen_pens[config->arrowbg].pen,0);
  482.                 DoArrow(rp,
  483.                     x_off+612,
  484.                     y_off+127,
  485.                     12,6,
  486.                     screen_pens[config->arrowfg].pen,screen_pens[config->arrowbg].pen,1);
  487.                 menusliderimage.PlaneOnOff=config->slidercol;
  488.                 FixSliderBody(Window,&menuslidergads[0],20,20-HIDDENLINES,0);
  489.                 FixSliderPot(Window,&menuslidergads[0],0,20,20-HIDDENLINES,2);
  490.                 do_menuscreen_title(STR_MENU_SCREEN);
  491.             }
  492.  
  493.         case CFG_DRIVE:
  494.             if (scr==CFG_DRIVE) {
  495.                 if (drivegads) AddGList(Window,drivegads,-1,DRIVECOUNT,NULL);
  496.                 initsidegads(drivegadgets,1,0);
  497.                 maingad[DRIVE_GETDRIVES].Activation&=~GACT_TOGGLESELECT;
  498.                 maingad[DRIVE_OKAY].Activation&=~GACT_TOGGLESELECT;
  499.                 maingad[DRIVE_CANCEL].Activation&=~GACT_TOGGLESELECT;
  500.                 do_menuscreen_title(STR_DRIVE_SCREEN);
  501.             }
  502.             dogadgetinfo(NULL);
  503.             break;
  504.  
  505.         case CFG_FILETYPE:
  506.             initsidegads(filetypeactiongadgets,1,0);
  507.             maingad[FILETYPE_NEW].Activation&=~GACT_TOGGLESELECT;
  508.             maingad[FILETYPE_OKAY].Activation&=~GACT_TOGGLESELECT;
  509.             maingad[FILETYPE_CANCEL].Activation&=~GACT_TOGGLESELECT;
  510.             doscreentitle(cfg_string[STR_FILETYPE_SCREEN]);
  511.             setuplist(&filetypeactionlist,12,14);
  512.             filetypeactionlist.itemselected=-1;
  513.             AddListView(&filetypeactionlist,1);
  514.             dogadgetinfo(NULL);
  515.             break;
  516.  
  517.         case CFG_SCREEN:
  518.             initsidegads(screengadgets,1,1);
  519.             if ((config->screenmode==MODE_WORKBENCHUSE ||
  520.                 config->screenmode==MODE_PUBLICSCREENUSE) &&
  521.                 version2<OSVER_39)
  522.                 DisableGadget(&maingad[SCREEN_PALETTE],rp,2,1);
  523.             doscreentitle(cfg_string[STR_SCREEN_SCREEN]);
  524.             break;
  525.  
  526.         case CFG_SYSTEM:
  527.             initsidegads(systemgads,1,1);
  528.             doscreentitle(cfg_string[STR_SYSTEM_SCREEN]);
  529.             break;
  530.  
  531.         case CFG_HOTKEYS:
  532.             initsidegads(hotkeysgadgets,1,0);
  533.             maingad[HOTKEYS_NEWHOTKEY].Activation&=~GACT_TOGGLESELECT;
  534.             maingad[HOTKEYS_OKAY].Activation&=~GACT_TOGGLESELECT;
  535.             maingad[HOTKEYS_CANCEL].Activation&=~GACT_TOGGLESELECT;
  536.             doscreentitle(cfg_string[STR_HOTKEYS_SCREEN]);
  537.             setuplist(&hotkeyslist,12,14);
  538.             hotkeyslist.itemselected=-1;
  539.             hotkeyslist.items=NULL;
  540.             hotkeyslist.topitem=0;
  541.             AddListView(&hotkeyslist,1);
  542.             dogadgetinfo(NULL);
  543.             break;
  544.     }
  545.     if (scr==CFG_MAINMENU) strcpy(currenthelpname,cfg_string[STR_MAIN_MENU]);
  546.     else strcpy(currenthelpname,mainmenugads[scr]);
  547. }
  548.  
  549. void initsidegads(gads,toggle,vert)
  550. char **gads;
  551. int toggle,vert;
  552. {
  553.     int num,a,x,y,x1,ac,dn,gnum,rnum,w,h;
  554.     struct Gadget *gadbuf;
  555.  
  556.     if (!gads) return;
  557.  
  558.     for (num=0,rnum=0;;rnum++) {
  559.         if (!gads[rnum]) break;
  560.         if (gads[rnum][0]) ++num;
  561.     }
  562.  
  563.     if (!(gadbuf=LAllocRemember(&gadgetkey,sizeof(struct Gadget)*num,MEMF_CLEAR)))
  564.         quit();
  565.  
  566.     h=12;
  567.     if (vert) {
  568.         x=x_off+8;
  569.         y=y_off+4;
  570.         w=112;
  571.     }
  572.     else {
  573.         dn=rnum/5;
  574.         if (dn*5==rnum) --dn;
  575.         ac=rnum-dn*5;
  576.         w=104;
  577.         x1=x=((Window->Width-(ac*(w+12)))/2)-2;
  578.         y=y_off+172-(dn*(h+2));
  579.     }
  580.     gnum=0;
  581.     for (a=0;a<rnum;a++) {
  582.         if (gads[a][0]) {
  583.             gadbuf[gnum].NextGadget=(gnum<num-1)?&gadbuf[gnum+1]:NULL;
  584.             gadbuf[gnum].LeftEdge=x; gadbuf[gnum].TopEdge=y;
  585.             gadbuf[gnum].Width=w; gadbuf[gnum].Height=h;
  586.             gadbuf[gnum].Flags=GFLG_GADGHCOMP;
  587.             gadbuf[gnum].Activation=GACT_RELVERIFY;
  588.             if (toggle) gadbuf[gnum].Activation|=GACT_TOGGLESELECT;
  589.             gadbuf[gnum].GadgetType=GTYP_BOOLGADGET;
  590.             gadbuf[gnum].GadgetID=gnum;
  591.             ++gnum;
  592.         }
  593.         if (vert) y+=(h+2);
  594.         else {
  595.             x+=(w+16);
  596.             if (x>(Window->Width-10-w)) {
  597.                 x=x1;
  598.                 y+=(h+2);
  599.             }
  600.         }
  601.     }
  602.     SetAPen(rp,screen_pens[1].pen);
  603.     AddGadgetBorders(&gadgetkey,
  604.         gadbuf,
  605.         gnum,
  606.         screen_pens[config->gadgettopcol].pen,screen_pens[config->gadgetbotcol].pen);
  607.     AddGadgets(Window,
  608.         gadbuf,
  609.         gads,
  610.         num,
  611.         screen_pens[config->gadgettopcol].pen,screen_pens[config->gadgetbotcol].pen,1);
  612.     maingad=gadbuf;
  613. }
  614.  
  615. void inittickgads(gads,flag,flag2)
  616. struct ConfigGadget *gads;
  617. int flag,flag2;
  618. {
  619.     int num,a,y,gad,last,lasty,dy,xp,yp,fl,b;
  620.     char **namearray;
  621.     struct StringInfo *sinfo;
  622.  
  623.     removetickgads();
  624.     if (!gads) return;
  625.  
  626.     num=0;
  627.     for (a=0;;a++) {
  628.         if (!gads[a].type) break;
  629.         if (gads[a].type!=CTYPE_TEXT && gads[a].type!=CTYPE_SKIP) ++num;
  630.     }
  631.  
  632.     if (!num) return;
  633.  
  634.     if (!(tickgad=LAllocRemember(&tickkey,sizeof(struct Gadget)*num,MEMF_CLEAR)) ||
  635.         !(namearray=LAllocRemember(&tickkey,num*4,MEMF_CLEAR))) return;
  636.  
  637.     y=y_off+46;
  638.     lasty=y;
  639.     gad=0;
  640.     dy=0;
  641.  
  642.     SetAPen(rp,screen_pens[1].pen);
  643.  
  644.     for (a=0;;a++) {
  645.         if (!gads[a].type) break;
  646.         if (gads[a].type==CTYPE_SKIP) continue;
  647.         switch (gads[a].type) {
  648.             case CTYPE_MOVE:
  649.                 y=y_off+(gads[a].x-12); dy=0;
  650.                 break;
  651.             case CTYPE_MOVEREL:
  652.                 dy=gads[a].x;
  653.                 break;
  654.             case CTYPE_TEXT:
  655.                 if (gads[a].x<0) xp=x_off+158;
  656.                 else xp=x_off+(gads[a].x-2);
  657.                 if (gads[a].y<0) {
  658.                     yp=y+8; dy=13;
  659.                 }
  660.                 else {
  661.                     yp=y_off+(gads[a].y-12);
  662.                     if (gads[a].value==1) {
  663.                         y=yp-8;
  664.                         dy=13;
  665.                     }
  666.                     else dy=0;
  667.                 }
  668.                 if (gads[a].nameentry>-1) UScoreText(rp,cfg_string[gads[a].nameentry],xp,yp,-1);
  669.                 break;
  670.             case CTYPE_GAD:
  671.             case CTYPE_RAD:
  672.             case CTYPE_MRAD:
  673.                 if (gads[a].nameentry>-1) namearray[gad]=cfg_string[gads[a].nameentry];
  674.                 else namearray[gad]=(char *)-1;
  675.                 tickgad[gad].NextGadget=(gad<num-1)?&tickgad[gad+1]:NULL;
  676.                 if (gads[a].type==CTYPE_GAD) {
  677.                     if (gads[a].w<0) tickgad[gad].Width=26;
  678.                     else tickgad[gad].Width=gads[a].w;
  679.                     if (gads[a].h<0) tickgad[gad].Height=11;
  680.                     else tickgad[gad].Height=gads[a].h;
  681.                     tickgad[gad].GadgetRender=checkoffimage;
  682.                     tickgad[gad].SelectRender=checkonimage;
  683.                     tickgad[gad].MutualExclude=GAD_CHECK;
  684.                     if (gads[a].x<0) xp=x_off+156;
  685.                     else xp=x_off+(gads[a].x-2);
  686.                     if (gads[a].y<0) {
  687.                         yp=y; dy=13;
  688.                     }
  689.                     else {
  690.                         yp=y_off+(gads[a].y-12); dy=0;
  691.                     }
  692.                     tickgad[gad].Activation=RELVERIFY|TOGGLESELECT;
  693.                 }
  694.                 else {
  695.                     if (gads[a].w<0) tickgad[gad].Width=15;
  696.                     else tickgad[gad].Width=gads[a].w;
  697.                     if (gads[a].h<0) tickgad[gad].Height=7;
  698.                     else tickgad[gad].Height=gads[a].h;
  699.                     tickgad[gad].GadgetRender=(APTR)buttonoffimage;
  700.                     tickgad[gad].SelectRender=(APTR)buttononimage;
  701.                     tickgad[gad].MutualExclude=GAD_RADIO;
  702.                     if (gads[a].x<0) xp=x_off+158;
  703.                     else xp=x_off+(gads[a].x-2);
  704.                     if (gads[a].y<0) {
  705.                         yp=y; dy=10;
  706.                     }
  707.                     else {
  708.                         yp=y_off+(gads[a].y-12); dy=0;
  709.                     }
  710.                     tickgad[gad].Activation=GADGIMMEDIATE|TOGGLESELECT;
  711.                 }
  712.                 tickgad[gad].LeftEdge=xp; tickgad[gad].TopEdge=yp;
  713.                 tickgad[gad].Flags=GADGIMAGE|GADGHIMAGE;
  714.                 if (gads[a].value==0) fl=flag;
  715.                 else if (gads[a].value==1) fl=flag2;
  716.                 if (gads[a].type==CTYPE_MRAD) {
  717.                     b=gads[a].mutualex&(~gads[a].bit);
  718.                     if (!(fl&b)) tickgad[gad].Flags|=SELECTED;
  719.                 }
  720.                 else if (fl && fl&gads[a].bit) tickgad[gad].Flags|=SELECTED;
  721.                 tickgad[gad].GadgetType=BOOLGADGET;
  722.                 tickgad[gad].GadgetID=GAD_BASE+(gads[a].value*4000)+gads[a].bit;
  723.                 tickgad[gad].UserData=(APTR)&gads[a];
  724.                 gads[a].gad=&tickgad[gad];
  725.                 last=gads[a].type; ++gad;
  726.                 break;
  727.             case CTYPE_STR:
  728.                 if (gads[a].y==-2) y=lasty;
  729.                 else {
  730.                     if (last==CTYPE_GAD || gads[a].type==CTYPE_RAD || gads[a].type==CTYPE_MRAD)
  731.                         ++y;
  732.                     ++y;
  733.                 }
  734.                 if (gads[a].bit&4 || gads[a].nameentry==-1) namearray[gad]=(char *)-1;
  735.                 else namearray[gad]=cfg_string[gads[a].nameentry];
  736.                 tickgad[gad].NextGadget=(gad<num-1)?&tickgad[gad+1]:NULL;
  737.                 if (gads[a].bit&4) {
  738.                     if (gads[a].x<0) xp=x_off+338;
  739.                     else xp=x_off+(gads[a].x-2);
  740.                     if (gads[a].y<0) {
  741.                         yp=y; dy=13;
  742.                     }
  743.                     else {
  744.                         yp=y_off+(gads[a].y-12); dy=0;
  745.                     }
  746.                 }
  747.                 else {
  748.                     if (gads[a].x<0) xp=x_off+306;
  749.                     else xp=x_off+(gads[a].x-2);
  750.                     if (gads[a].y<0) {
  751.                         yp=y; dy=13;
  752.                     }
  753.                     else {
  754.                         yp=y_off+(gads[a].y-12); dy=0;
  755.                     }
  756.                 }
  757.                 if (gads[a].w<0) {
  758.                     tickgad[gad].Width=Window->Width-xp-30;
  759.                     if (gads[a].bit&4) tickgad[gad].Width-=2;
  760.                 }
  761.                 else tickgad[gad].Width=gads[a].w;
  762.                 if (gads[a].h<0) tickgad[gad].Height=8;
  763.                 else tickgad[gad].Height=gads[a].h;
  764.                 tickgad[gad].LeftEdge=xp; tickgad[gad].TopEdge=yp;
  765.                 tickgad[gad].Flags=GFLG_GADGHCOMP|GFLG_STRINGEXTEND|GFLG_TABCYCLE;
  766.                 tickgad[gad].Activation=GACT_RELVERIFY|GACT_TOGGLESELECT;
  767.                 if (gads[a].bit&1) tickgad[gad].Activation|=GACT_LONGINT;
  768.                 if (gads[a].bit&4) {
  769.                     tickgad[gad].MutualExclude=1;
  770.                     ++y;
  771.                 }
  772.                 tickgad[gad].GadgetType=GTYP_STRGADGET;
  773.                 if (sinfo=(struct StringInfo *)LAllocRemember(&tickkey,sizeof(struct StringInfo),MEMF_CLEAR)) {
  774.                     sinfo->Buffer=(STRPTR)LAllocRemember(&tickkey,gads[a].mutualex,MEMF_CLEAR);
  775.                     sinfo->MaxChars=gads[a].mutualex;
  776.                     sinfo->Extension=&stringex;
  777.                 }
  778.                 tickgad[gad].SpecialInfo=(APTR)sinfo;
  779.                 tickgad[gad].GadgetID=STRING_BASE+gad;
  780.                 tickgad[gad].UserData=(APTR)&gads[a];
  781.                 gads[a].gad=&tickgad[gad];
  782.                 last=gads[a].type; ++gad;
  783.                 break;
  784.             case CTYPE_REQ:
  785.                 y=lasty;
  786.                 if (gads[a].x<0) xp=x_off+302;
  787.                 else xp=x_off+(gads[a].x-2);
  788.                 if (gads[a].y<0) {
  789.                     yp=y-4; dy=13;
  790.                 }
  791.                 else {
  792.                     yp=y_off+(gads[a].y-12); dy=0;
  793.                 }
  794.                 if (gads[a].nameentry>-1) namearray[gad]=cfg_string[gads[a].nameentry];
  795.                 else namearray[gad]=(char *)-1;
  796.                 tickgad[gad].NextGadget=(gad<num-1)?&tickgad[gad+1]:NULL;
  797.                 tickgad[gad].LeftEdge=xp; tickgad[gad].TopEdge=yp;
  798.                 if (gads[a].w<0) tickgad[gad].Width=28;
  799.                 else tickgad[gad].Width=gads[a].w;
  800.                 if (gads[a].h<0) tickgad[gad].Height=14;
  801.                 else tickgad[gad].Height=gads[a].h;
  802.                 tickgad[gad].Flags=GADGHCOMP;
  803.                 tickgad[gad].Activation=RELVERIFY;
  804.                 tickgad[gad].GadgetType=BOOLGADGET;
  805.                 tickgad[gad].GadgetID=REQ_BASE+gad;
  806.                 tickgad[gad].MutualExclude=GAD_GLASS;
  807.                 tickgad[gad].UserData=(APTR)&gads[a];
  808.                 AddGadgetBorders(&tickkey,
  809.                     &tickgad[gad],
  810.                     1,
  811.                     screen_pens[config->gadgettopcol].pen,screen_pens[config->gadgetbotcol].pen);
  812.                 doglassimage(&tickgad[gad]);
  813.                 gads[a].gad=&tickgad[gad-1];
  814.                 last=gads[a].type; ++gad;
  815.                 break;
  816.         }
  817.         lasty=y; y+=dy;
  818.     }
  819.     AddGadgets(Window,
  820.         tickgad,
  821.         namearray,
  822.         num,
  823.         screen_pens[config->gadgettopcol].pen,screen_pens[config->gadgetbotcol].pen,1);
  824.     tickcount=num;
  825. }
  826.  
  827. void removetickgads()
  828. {
  829.     if (tickgad && tickcount) {
  830.         RemoveGList(Window,tickgad,tickcount);
  831.         tickgad=NULL; tickcount=0;
  832.     }
  833.     LFreeRemember(&tickkey);
  834.     SetAPen(rp,screen_pens[0].pen);
  835.     RectFill(rp,
  836.         x_off+122,y_off+1,
  837.         x_bot,y_bot);
  838. }
  839.  
  840. processtickgad(gads,flag,sel,num)
  841. struct ConfigGadget *gads;
  842. int flag,sel,num;
  843. {
  844.     int a,ref=0,hitgad=-1;
  845.     struct Gadget *gad;
  846.  
  847.     for (a=0;;a++) {
  848.         if (!gads[a].type) break;
  849.         if (num==-1 || gads[a].value==num) {
  850.             if (gads[a].type==CTYPE_GAD || gads[a].type==CTYPE_RAD || gads[a].type==CTYPE_MRAD) {
  851.                 if (gads[a].bit==sel) {
  852.                     hitgad=a;
  853.                     break;
  854.                 }
  855.             }
  856.         }
  857.     }
  858.  
  859.     flag=0;
  860.     for (a=0;;a++) {
  861.         if (!gads[a].type) break;
  862.         if (num==-1 || gads[a].value==num) {
  863.             gad=gads[a].gad;
  864.             if (gads[a].type==CTYPE_GAD || gads[a].type==CTYPE_RAD || gads[a].type==CTYPE_MRAD) {
  865.                 if (a==hitgad) {
  866.                     if (!(gad->Flags&SELECTED) && gads[a].mutualex&sel) {
  867.                         gad->Flags|=SELECTED;
  868.                         ref=1;
  869.                     }
  870.                 }
  871.                 else {
  872.                     if (gad->Flags&SELECTED) {
  873.                         if (gads[a].type==CTYPE_MRAD) {
  874.                             if (gads[a].mutualex&sel) {
  875.                                 gad->Flags&=~SELECTED;
  876.                                 ref=1;
  877.                             }
  878.                         }
  879.                         else if (gads[hitgad].mutualex&gads[a].bit) {
  880.                             gad->Flags&=~SELECTED;
  881.                             ref=1;
  882.                         }
  883.                     }
  884.                 }
  885.                 if (gads[a].type!=CTYPE_MRAD && gad->Flags&SELECTED) flag|=gads[a].bit;
  886.             }
  887.             else if (gads[a].type==CTYPE_STR) {
  888.                 if (gads[a].buffer) {
  889.                     if (gads[a].bit&2) CheckHexGad(gad,Window,0,0xff);
  890.                     strcpy(gads[a].buffer,(char *)((struct StringInfo *)gad->SpecialInfo)->Buffer);
  891.                 }
  892.             }
  893.         }
  894.     }
  895.     if (ref) RefreshGList(tickgad,Window,NULL,tickcount);
  896.     return(flag);
  897. }
  898.  
  899. struct ConfigUndo *makeundo(type)
  900. int type;
  901. {
  902.     struct ConfigUndo *undo;
  903.     struct DOpusRemember *key;
  904.     struct dopusgadgetbanks *bank,*newbank,*curbank;
  905.     struct dopushotkey *hotkey,*newhotkey,*curhotkey;
  906.     int a;
  907.  
  908.     key=NULL;
  909.     if (!(undo=LAllocRemember(&key,sizeof(struct ConfigUndo),MEMF_CLEAR)))
  910.         return(0);
  911.     if (type&UNDO_MAIN)
  912.         undo->config=(struct Config *)getcopy((char *)config,sizeof(struct Config),&key);
  913.     if (type&UNDO_GADGET) {
  914.         bank=firstbank; curbank=NULL;
  915.         while (bank) {
  916.             if (newbank=(struct dopusgadgetbanks *)
  917.                 getcopy((char *)bank,sizeof(struct dopusgadgetbanks),&key)) {
  918.                 newbank->next=NULL;
  919.                 copygadgets(bank,newbank,&key);
  920.                 if (curbank) curbank->next=newbank;
  921.                 else undo->firstbank=newbank;
  922.                 curbank=newbank;
  923.             }
  924.             bank=bank->next;
  925.         }
  926.     }
  927.     if (type&UNDO_MENU &&
  928.         (undo->menu=(struct newdopusfunction *)
  929.             getcopy((char *)config->menu,sizeof(struct newdopusfunction)*MENUCOUNT,&key))) {
  930.         for (a=0;a<MENUCOUNT;a++) {
  931.             undo->menu[a].name=getcopy(config->menu[a].name,-1,&key);
  932.             undo->menu[a].function=getcopy(config->menu[a].function,-1,&key);
  933.         }
  934.         for (a=0;a<5;a++) strcpy(undo->menutit[a],config->menutit[a]);
  935.     }
  936.     if (type&UNDO_DRIVE &&
  937.         (undo->drive=(struct dopusfunction *)
  938.             getcopy((char *)config->drive,sizeof(struct dopusfunction)*DRIVECOUNT,&key))) {
  939.         for (a=0;a<DRIVECOUNT;a++)
  940.             undo->drive[a].function=getcopy(config->drive[a].function,-1,&key);
  941.     }
  942.     if (type&UNDO_FILETYPE)
  943.         copyfiletypes(firsttype,&undo->firsttype,&key);
  944.     if (type&UNDO_HOTKEYS) {
  945.         hotkey=firsthotkey; curhotkey=NULL;
  946.         while (hotkey) {
  947.             if (newhotkey=(struct dopushotkey *)
  948.                     getcopy((char *)hotkey,sizeof(struct dopushotkey),&key)) {
  949.                 newhotkey->func.function=getcopy(hotkey->func.function,-1,&key);
  950.                 newhotkey->next=NULL;
  951.                 if (curhotkey) curhotkey->next=newhotkey;
  952.                 else undo->firsthotkey=newhotkey;
  953.                 curhotkey=newhotkey;
  954.             }
  955.             hotkey=hotkey->next;
  956.         }
  957.     }
  958.     undo->key=key;
  959.     return(undo);
  960. }
  961.  
  962. void copygadgets(bank1,bank2,key)
  963. struct dopusgadgetbanks *bank1,*bank2;
  964. struct DOpusRemember **key;
  965. {
  966.     int a;
  967.  
  968.     for (a=0;a<84;a++) {
  969.         bank2->gadgets[a].name=getcopy(bank1->gadgets[a].name,-1,key);
  970.         bank2->gadgets[a].function=getcopy(bank1->gadgets[a].function,-1,key);
  971.     }
  972. }
  973.  
  974. void copyfiletypes(oldfirst,newfirst,key)
  975. struct dopusfiletype *oldfirst,**newfirst;
  976. struct DOpusRemember **key;
  977. {
  978.     struct dopusfiletype *type,*newtype,*curtype=NULL;
  979.     int a;
  980.  
  981.     type=oldfirst;
  982.     *newfirst=NULL;
  983.     while (type) {
  984.         if (newtype=(struct dopusfiletype *)
  985.             getcopy((char *)type,sizeof(struct dopusfiletype),key)) {
  986.             for (a=0;a<FILETYPE_FUNCNUM;a++)
  987.                 newtype->function[a]=getcopy(type->function[a],-1,key);
  988.             newtype->recognition=getcopy(type->recognition,-1,key);
  989.             newtype->iconpath=getcopy(type->iconpath,-1,key);
  990.             if (curtype) curtype->next=newtype;
  991.             else *newfirst=newtype;
  992.             curtype=newtype;
  993.             curtype->next=NULL;
  994.         }
  995.         type=type->next;
  996.     }
  997. }
  998.  
  999. void doundo(undo,type)
  1000. struct ConfigUndo *undo;
  1001. int type;
  1002. {
  1003.     struct DOpusRemember *key;
  1004.     struct dopusgadgetbanks *bank,*curbank,*newbank;
  1005.     struct dopushotkey *hotkey,*curhotkey,*newhotkey;
  1006.     int a;
  1007.  
  1008.     if (!undo) return;
  1009.     if (!type) {
  1010.         key=undo->key;
  1011.         LFreeRemember(&key);
  1012.     }
  1013.     else {
  1014.         if (type&UNDO_MENU) {
  1015.             for (a=0;a<MENUCOUNT;a++) freenewfunction(&config->menu[a]);
  1016.         }
  1017.         if (type&UNDO_DRIVE) for (a=0;a<DRIVECOUNT;a++) freefunction(&config->drive[a]);
  1018.         if (type&UNDO_MAIN && undo->config)
  1019.             copyconfigonly(undo->config,config);
  1020.         if (type&UNDO_GADGET) {
  1021.             freegadgets(firstbank); firstbank=NULL;
  1022.             bank=undo->firstbank; curbank=NULL;
  1023.             while (bank) {
  1024.                 if (newbank=(struct dopusgadgetbanks *)
  1025.                     getcopy((char *)bank,sizeof(struct dopusgadgetbanks),NULL)) {
  1026.                     newbank->next=NULL;
  1027.                     copygadgets(bank,newbank,NULL);
  1028.                     if (curbank) curbank->next=newbank;
  1029.                     else firstbank=newbank;
  1030.                     curbank=newbank;
  1031.                 }
  1032.                 bank=bank->next;
  1033.             }
  1034.         }
  1035.         if (type&UNDO_MENU && undo->menu) {
  1036.             CopyMem((char *)undo->menu,(char *)config->menu,sizeof(struct newdopusfunction)*MENUCOUNT);
  1037.             for (a=0;a<MENUCOUNT;a++) {
  1038.                 config->menu[a].name=getcopy(undo->menu[a].name,-1,NULL);
  1039.                 config->menu[a].function=getcopy(undo->menu[a].function,-1,NULL);
  1040.             }
  1041.             for (a=0;a<5;a++) strcpy(config->menutit[a],undo->menutit[a]);
  1042.         }
  1043.         if (type&UNDO_DRIVE && undo->drive) {
  1044.             CopyMem((char *)undo->drive,(char *)config->drive,sizeof(struct dopusfunction)*DRIVECOUNT);
  1045.             for (a=0;a<DRIVECOUNT;a++)
  1046.                 config->drive[a].function=getcopy(undo->drive[a].function,-1,NULL);
  1047.         }
  1048.         if (type&UNDO_FILETYPE) {
  1049.             LFreeRemember(&typekey); firsttype=NULL;
  1050.             copyfiletypes(undo->firsttype,&firsttype,&typekey);
  1051.         }
  1052.         if (type&UNDO_HOTKEYS) {
  1053.             hotkey=firsthotkey;
  1054.             while (hotkey) {
  1055.                 curhotkey=hotkey->next;
  1056.                 freestring(hotkey->func.function);
  1057.                 FreeMem(hotkey,sizeof(struct dopushotkey));
  1058.                 hotkey=curhotkey;
  1059.             }
  1060.             firsthotkey=NULL; curhotkey=NULL;
  1061.             hotkey=undo->firsthotkey;
  1062.             while (hotkey) {
  1063.                 if (newhotkey=(struct dopushotkey *)
  1064.                     getcopy((char *)hotkey,sizeof(struct dopushotkey),NULL)) {
  1065.                     newhotkey->func.function=getcopy(hotkey->func.function,-1,NULL);
  1066.                     newhotkey->next=NULL;
  1067.                     if (curhotkey) curhotkey->next=newhotkey;
  1068.                     else firsthotkey=newhotkey;
  1069.                     curhotkey=newhotkey;
  1070.                 }
  1071.                 hotkey=hotkey->next;
  1072.             }
  1073.         }
  1074.     }
  1075. }
  1076.  
  1077. void freegadgets(first)
  1078. struct dopusgadgetbanks *first;
  1079. {
  1080.     struct dopusgadgetbanks *temp;
  1081.  
  1082.     while (first) {
  1083.         temp=first->next;
  1084.         freegadgetbank(first,1);
  1085.         first=temp;
  1086.     }
  1087. }
  1088.  
  1089. void freegadgetbank(bank,free)
  1090. struct dopusgadgetbanks *bank;
  1091. int free;
  1092. {
  1093.     int a;
  1094.  
  1095.     if (bank) {
  1096.         for (a=0;a<GADCOUNT;a++) {
  1097.             freestring(bank->gadgets[a].name);
  1098.             freestring(bank->gadgets[a].function);
  1099.         }
  1100.         if (free) FreeMem(bank,sizeof(struct dopusgadgetbanks));
  1101.     }
  1102. }
  1103.  
  1104. void freefunction(func)
  1105. struct dopusfunction *func;
  1106. {
  1107.     freestring(func->function);
  1108.     func->function=NULL;
  1109. }
  1110.  
  1111. void freenewfunction(func)
  1112. struct newdopusfunction *func;
  1113. {
  1114.     freestring(func->name); func->name=NULL;
  1115.     freestring(func->function); func->function=NULL;
  1116. }
  1117.  
  1118. char *getcopy(object,size,key)
  1119. char *object;
  1120. int size;
  1121. struct DOpusRemember **key;
  1122. {
  1123.     char *newobject;
  1124.  
  1125.     if (!object) return(NULL);
  1126.     if (size==-1) size=strlen(object)+1;
  1127.     if (key) newobject=(char *)LAllocRemember(key,size,MEMF_CLEAR);
  1128.     else newobject=AllocMem(size,MEMF_CLEAR);
  1129.     if (newobject) CopyMem((char *)object,(char *)newobject,size);
  1130.     return(newobject);
  1131. }
  1132.  
  1133. void makestring(char *buf,...)
  1134. {
  1135.     va_list ap;
  1136.     char *ptr;
  1137.     struct Gadget *gad,*first=NULL;
  1138.     struct ConfigGadget *cgad;
  1139.  
  1140.     if (!tickgad) return;
  1141.     gad=tickgad;
  1142.  
  1143.     va_start(ap,buf);
  1144.     while (buf && gad) {
  1145.         if (gad->GadgetType==STRGADGET) {
  1146.             cgad=(struct ConfigGadget *)gad->UserData;
  1147.             cgad->buffer=buf;
  1148.             ptr=(char *)((struct StringInfo *)gad->SpecialInfo)->Buffer;
  1149.             strcpy(ptr,buf);
  1150.             RefreshStrGad(gad,Window);
  1151.             if (!first) first=gad;
  1152.             buf=(char *)va_arg(ap,char *);
  1153.         }
  1154.         gad=gad->NextGadget;
  1155.     }
  1156.     if (first) ActivateStrGad(first,Window);
  1157. }
  1158.  
  1159. getstring(text,buf,len,num)
  1160. char *text,*buf;
  1161. int len,num;
  1162. {
  1163.     struct DOpusSimpleRequest req;
  1164.     char *gads[3];
  1165.     static int rets[2]={1,0};
  1166.     int a;
  1167.  
  1168.     gads[0]=cfg_string[STR_OKAY];
  1169.     gads[1]=cfg_string[STR_CANCEL];
  1170.     gads[2]=NULL;
  1171.  
  1172.     req.text=text;
  1173.     req.gads=gads;
  1174.     req.rets=rets;
  1175.     req.hi=screen_pens[config->gadgettopcol].pen;
  1176.     req.lo=screen_pens[config->gadgetbotcol].pen;
  1177.     req.fg=screen_pens[config->requestfg].pen;
  1178.     req.bg=screen_pens[config->requestbg].pen;
  1179.     req.strbuf=buf;
  1180.     req.strlen=len;
  1181.     req.flags=num|SRF_BORDERS|SRF_RECESSHI|SRF_EXTEND;
  1182.     req.value=(int)&stringex;
  1183.     req.font=NULL;
  1184.     req.title="ConfigOpus";
  1185.     busy();
  1186.     a=DoSimpleRequest(Window,&req);
  1187.     unbusy();
  1188.     return(a);
  1189. }
  1190.  
  1191. request(text)
  1192. char *text;
  1193. {
  1194.     return(do_request(text,cfg_string[STR_OKAY],cfg_string[STR_CANCEL]));
  1195. }
  1196.  
  1197. do_request(text,pos,neg)
  1198. char *text,*pos,*neg;
  1199. {
  1200.     struct DOpusSimpleRequest req;
  1201.     char *gads[3];
  1202.     static int rets[2]={1,0};
  1203.     int a;
  1204.  
  1205.     gads[0]=pos;
  1206.     gads[1]=neg;
  1207.     gads[2]=NULL;
  1208.  
  1209.     req.text=text;
  1210.     req.gads=gads;
  1211.     req.rets=rets;
  1212.     req.hi=screen_pens[config->gadgettopcol].pen;
  1213.     req.lo=screen_pens[config->gadgetbotcol].pen;
  1214.     req.fg=screen_pens[config->requestfg].pen;
  1215.     req.bg=screen_pens[config->requestbg].pen;
  1216.     req.strbuf=NULL;
  1217.     req.flags=SRF_BORDERS|SRF_RECESSHI;
  1218.     req.font=NULL;
  1219.     req.title="ConfigOpus";
  1220.     busy();
  1221.     a=DoSimpleRequest(Window,&req);
  1222.     unbusy();
  1223.     return(a);
  1224. }
  1225.  
  1226. void doglassimage(gad)
  1227. struct Gadget *gad;
  1228. {
  1229.     int a,o;
  1230.  
  1231.     o=rp->FgPen;
  1232.     SetDrMd(rp,JAM1);
  1233.     SetAPen(rp,screen_pens[config->gadgetbotcol].pen);
  1234.     for (a=0;a<2;a++) {
  1235.         BltTemplate((char *)glass_data[a],0,4,rp,gad->LeftEdge+4,gad->TopEdge+2,20,9);
  1236.         SetAPen(rp,screen_pens[config->gadgettopcol].pen);
  1237.     }
  1238.     SetDrMd(rp,JAM2);
  1239.     SetAPen(rp,o);
  1240. }
  1241.  
  1242. void freestring(str)
  1243. char *str;
  1244. {
  1245.     if (str) FreeMem(str,strlen(str)+1);
  1246. }
  1247.  
  1248. static char lasttitle[80];
  1249.  
  1250. void doscreentitle(str)
  1251. char *str;
  1252. {
  1253.     if (str && str!=(char *)-1) strcpy(lasttitle,str);
  1254.     SetWindowTitles(Window,lasttitle,(char *)-1);
  1255. }
  1256.  
  1257. struct IntuiMessage *getintuimsg()
  1258. {
  1259.     struct IntuiMessage *msg;
  1260.     struct MenuItem *item;
  1261.     int a;
  1262.     char buf[10],c;
  1263.  
  1264.     if (msg=(struct IntuiMessage *)GetMsg(Window->UserPort)) {
  1265.         if (msg->Class==IDCMP_RAWKEY) {
  1266.             if (msg->Qualifier&IEQUALIFIER_RCOMMAND && Window->MenuStrip) {
  1267.                 if (!(msg->Code&0x80)) {
  1268.                     RawkeyToStr(msg->Code,0,NULL,buf,10); c=LToUpper(buf[0]);
  1269.                     item=Window->MenuStrip->FirstItem;
  1270.                     a=0;
  1271.                     while (item) {
  1272.                         if (item->Command && c==item->Command) {
  1273.                             msg->Class=MENUPICK;
  1274.                             msg->Code=a<<5;
  1275.                             break;
  1276.                         }
  1277.                         item=item->NextItem;
  1278.                         ++a;
  1279.                     }
  1280.                 }
  1281.             }
  1282.             else if (msg->Code==0x5f && help_ok) {
  1283.                 doconfighelp();
  1284.                 ReplyMsg((struct Message *)msg);
  1285.                 msg=NULL;
  1286.             }
  1287.         }
  1288.         else if (msg->Class==IDCMP_MENUPICK) {
  1289.             doscreentitle((char *)-1);
  1290.             if (Window->MenuStrip==&projectmenu && MENUNUM(msg->Code)==0) {
  1291.                 a=0;
  1292.                 switch (ITEMNUM(msg->Code)) {
  1293.                     case 3: dosave(0); a=1; break;
  1294.                     case 4: dosave(1); a=1; break;
  1295.                 }
  1296.                 if (a) {
  1297.                     ReplyMsg((struct Message *)msg);
  1298.                     msg=NULL;
  1299.                 }
  1300.             }
  1301.         }
  1302.         else if (msg->Class==IDCMP_MOUSEMOVE && Window->MenuStrip) {
  1303.             if (msg->MouseY>Window->BorderTop && msg->MouseY<Window->Height &&
  1304.                 msg->MouseX>=0 && msg->MouseX<Window->Width) Window->Flags|=RMBTRAP;
  1305.             else Window->Flags&=~RMBTRAP;
  1306.         }
  1307.     }
  1308.     return(msg);
  1309. }
  1310.  
  1311. struct TextFont *getfont(font,size,flags)
  1312. char *font;
  1313. int *size,flags;
  1314. {
  1315.     BPTR lock;
  1316.     struct TextFont *tf;
  1317.     static struct TextAttr sfont={NULL,0,0,0};
  1318.  
  1319.     sfont.ta_Name=(STRPTR)font; sfont.ta_YSize=*size;
  1320.     if ((tf=OpenFont(&sfont)) && tf->tf_YSize==sfont.ta_YSize &&
  1321.         (!(tf->tf_Flags&FPF_PROPORTIONAL) || flags!=FFLAG_NOPROP)) return(tf);
  1322.     if (tf) CloseFont(tf);
  1323.     if (!(lock=Lock("FONTS:",ACCESS_READ))) {
  1324.         strcpy(font,"topaz.font"); *size=8; sfont.ta_YSize=8;
  1325.         return((OpenFont(&sfont)));
  1326.     }
  1327.     UnLock(lock);
  1328.     if (!DiskfontBase || !(tf=OpenDiskFont(&sfont))) {
  1329.         if ((tf=OpenFont(&sfont))) *size=tf->tf_YSize;
  1330.     }
  1331.     if (!tf ||
  1332.         (!tf && flags!=FFLAG_8ONLY) ||
  1333.         (tf && flags==FFLAG_NOPROP && tf->tf_Flags&FPF_PROPORTIONAL)) {
  1334.         if (tf) CloseFont(tf);
  1335.         strcpy(font,"topaz.font"); *size=8; sfont.ta_YSize=8;
  1336.         tf=OpenFont(&sfont);
  1337.     }
  1338.     return(tf);
  1339. }
  1340.  
  1341. void loadrgb4(scr,pal,num)
  1342. struct Screen *scr;
  1343. USHORT *pal;
  1344. int num;
  1345. {
  1346.     int a,b;
  1347.     ULONG *data;
  1348.  
  1349.     if (data=AllocMem(num*3*sizeof(ULONG),0)) {
  1350.         for (a=0,b=0;a<num;a++) {
  1351.             data[b++]=(((pal[a]>>8)&0xf)<<28)|0x0fffffff;
  1352.             data[b++]=(((pal[a]>>4)&0xf)<<28)|0x0fffffff;
  1353.             data[b++]=((pal[a]&0xf)<<28)|0x0fffffff;
  1354.         }
  1355.         load_palette(scr,data,num);
  1356.         FreeMem(data,num*3*sizeof(ULONG));
  1357.     }
  1358. }
  1359.  
  1360. void load_palette(screen,palette,numcols)
  1361. struct Screen *screen;
  1362. ULONG *palette;
  1363. {
  1364.     if (!screen) {
  1365.         if (version2>=OSVER_39) {
  1366.             int a,b;
  1367.  
  1368.             for (a=0,b=0;a<numcols;a++) {
  1369.                 SetRGB32(&Window->WScreen->ViewPort,
  1370.                     screen_pens[a].pen,
  1371.                     palette[b++],palette[b++],palette[b++]);
  1372.             }
  1373.         }
  1374.     }
  1375.     else if (version2>=OSVER_39) {
  1376.         ULONG *backup_palette;
  1377.  
  1378.         if (backup_palette=AllocMem(((numcols*3)+2)*sizeof(ULONG),MEMF_CLEAR)) {
  1379.             CopyMem((char *)palette,(char *)&backup_palette[1],(numcols*3)*sizeof(ULONG));
  1380.             backup_palette[0]=numcols<<16;
  1381.             backup_palette[(numcols*3)+1]=0;
  1382.             LoadRGB32(&screen->ViewPort,backup_palette);
  1383.             FreeMem(backup_palette,((numcols*3)+2)*sizeof(ULONG));
  1384.         }
  1385.     }
  1386.     else {
  1387.         UWORD backup_palette[16];
  1388.         int a,b;
  1389.  
  1390.         for (a=0,b=0;a<numcols*3;b++) {
  1391.             backup_palette[b]=0;
  1392.             backup_palette[b]|=(palette[a++]&0xf0000000)>>20;
  1393.             backup_palette[b]|=(palette[a++]&0xf0000000)>>24;
  1394.             backup_palette[b]|=(palette[a++]&0xf0000000)>>28;
  1395.         }
  1396.  
  1397.         LoadRGB4(&screen->ViewPort,backup_palette,numcols);
  1398.     }
  1399. }
  1400.  
  1401. void get_palette(screen,palette,numcols)
  1402. struct Screen *screen;
  1403. ULONG *palette;
  1404. int numcols;
  1405. {
  1406.     if (!screen) {
  1407.         if (version2>=OSVER_39) {
  1408.             int a,b;
  1409.  
  1410.             for (a=0,b=0;a<numcols;a++,b+=3) {
  1411.                 GetRGB32(Window->WScreen->ViewPort.ColorMap,
  1412.                     screen_pens[a].pen,    
  1413.                     1,
  1414.                     &palette[b]);
  1415.             }
  1416.         }
  1417.     }
  1418.     else if (version2>=OSVER_39) {
  1419.         GetRGB32(screen->ViewPort.ColorMap,0,numcols,palette);
  1420.     }
  1421.     else {
  1422.         int a,b;
  1423.         ULONG colour;
  1424.  
  1425.         for (a=0,b=0;a<numcols;a++) {
  1426.             colour=GetRGB4(screen->ViewPort.ColorMap,a);
  1427.             palette[b++]=(((colour>>8)&0xf)<<28)|0x0fffffff;
  1428.             palette[b++]=(((colour>>4)&0xf)<<28)|0x0fffffff;
  1429.             palette[b++]=((colour&0xf)<<28)|0x0fffffff;
  1430.         }
  1431.     }
  1432. }
  1433.  
  1434. void open_screen()
  1435. {
  1436.     if (!Window) {
  1437.         int a,onworkbench=0;
  1438.         struct Screen *wbscreen=NULL,*usescreen;
  1439.  
  1440.         if (tfont) CloseFont(tfont);
  1441.         a=8;
  1442.         tfont=getfont(config->fontbufs[0],&a,FFLAG_8ONLY);
  1443.         strcpy(sfont.ta_Name,tfont->tf_Message.mn_Node.ln_Name);
  1444.  
  1445.         if (version2>=OSVER_39) {
  1446.             if (wbscreen=LockPubScreen(NULL)) {
  1447.                 if (wbscreen->Height>wbscreen->WBorTop+wbscreen->Font->ta_YSize+189) {
  1448.                     int pen,num;
  1449.                     struct ColorMap *cm;
  1450.  
  1451.                     cm=wbscreen->ViewPort.ColorMap;
  1452.                     num=1<<config->scrdepth;
  1453.  
  1454.                     for (pen=0;pen<num;pen++) {
  1455.                         screen_pens[pen].red=config->new_palette[(pen*3)];
  1456.                         screen_pens[pen].green=config->new_palette[(pen*3)+1];
  1457.                         screen_pens[pen].blue=config->new_palette[(pen*3)+2];
  1458.                         if ((screen_pens[pen].pen=
  1459.                             ObtainPen(cm,-1,
  1460.                                 screen_pens[pen].red,
  1461.                                 screen_pens[pen].green,
  1462.                                 screen_pens[pen].blue,
  1463.                                 PEN_EXCLUSIVE))==-1) break;
  1464.                         screen_pens[pen].alloc=1;
  1465.                     }
  1466.  
  1467.                     if (pen<num) free_colour_table(cm);
  1468.                     else onworkbench=1;
  1469.                 }
  1470.             }
  1471.         }
  1472.  
  1473.         configscr.Depth=config->scrdepth;
  1474.         if (!onworkbench) {
  1475.             while (!(Screen=OpenScreen((struct NewScreen *)&configscr))) {
  1476.                 if (configscr.Depth<=2) quit();
  1477.                 --configscr.Depth;
  1478.             }
  1479.             ShowTitle(Screen,FALSE);
  1480.             usescreen=Screen;
  1481.         }
  1482.         else usescreen=wbscreen;
  1483.  
  1484.         vp=&usescreen->ViewPort;
  1485.         config->scrdepth=configscr.Depth;
  1486.         screen_depth=configscr.Depth;
  1487.  
  1488.         configwin.Screen=usescreen;
  1489.         configwin.Height=usescreen->WBorTop+usescreen->Font->ta_YSize+189;
  1490.  
  1491.         configwin.LeftEdge=0;
  1492.         configwin.TopEdge=usescreen->Font->ta_YSize+3;
  1493.  
  1494.         if (!Screen) {
  1495.             if (config->config_x>-1) configwin.LeftEdge=config->config_x;
  1496.             if (config->config_y>-1) configwin.TopEdge=config->config_y;
  1497.         }
  1498.  
  1499.         if (configwin.Width+configwin.LeftEdge>usescreen->Width)
  1500.             configwin.LeftEdge=usescreen->Width-configwin.Width;
  1501.  
  1502.         if (configwin.Height+configwin.TopEdge>usescreen->Height)
  1503.             configwin.TopEdge=usescreen->Height-configwin.Height;
  1504.  
  1505.         if (!(Window=OpenWindow(&configwin))) quit();
  1506.  
  1507.         if (!Screen) SetWindowTitles(Window,(char *)-1,configscr.DefaultTitle);
  1508.  
  1509.         rp=Window->RPort;
  1510.         FSSetMenuStrip(Window,&projectmenu);
  1511.  
  1512.         x_off=Window->BorderLeft;
  1513.         y_off=Window->BorderTop;
  1514.         x_bot=Window->Width-Window->BorderRight-1;
  1515.         y_bot=Window->Height-Window->BorderBottom-1;
  1516.  
  1517.         if (tfont) SetFont(rp,tfont);
  1518.         if (wbscreen) UnlockPubScreen(NULL,wbscreen);
  1519.     }
  1520.  
  1521.     load_palette(Screen,config->new_palette,1<<screen_depth);
  1522.  
  1523.     doradiobuttons();
  1524.     fix_gadget_positions();
  1525.     if (Screen || cmdport) ScreenToFront(Window->WScreen);
  1526. }
  1527.  
  1528. void close_screen()
  1529. {
  1530.     free_colour_table((Window)?Window->WScreen->ViewPort.ColorMap:NULL);
  1531.     if (Window) {
  1532.         if (Window->MenuStrip) ClearMenuStrip(Window);
  1533.         CloseWindow(Window);
  1534.         Window=NULL;
  1535.     }
  1536.     if (Screen) {
  1537.         CloseScreen(Screen);
  1538.         Screen=NULL;
  1539.     }
  1540. }
  1541.  
  1542. void free_colour_table(cm)
  1543. struct ColorMap *cm;
  1544. {
  1545.     int a;
  1546.  
  1547.     if (version2>=OSVER_39 && cm) {
  1548.         for (a=0;a<16;a++) {
  1549.             if (screen_pens[a].alloc)
  1550.                 ReleasePen(cm,screen_pens[a].pen);
  1551.         }
  1552.     }
  1553.  
  1554.     for (a=0;a<16;a++) {
  1555.         screen_pens[a].pen=a;
  1556.         screen_pens[a].alloc=0;
  1557.     }
  1558. }
  1559.